﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

// std headers
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>

// qt headers
#include <QObject>

// custom headers
#include "ComponentData.h"

#include "GcsService.h"
#include "IProjectComponent.h"
#include "IDetailedProjectComponent.h"
#include "IParameter.gcs.h"
#include "Major.h"


template<typename T> class QList;
class QNetworkReply;
class QNetworkAccessManager;
class QNetworkRequest;

namespace gmepgcs
{
    struct IParameter;
    struct IPerformanceCurveDefinition;
    struct IPerformanceCurve;
    struct ILegend; 
    struct ISpecification;
    
    template<typename TResult> class CustomReply;
    template<typename TData> class IPagedData;
    class CustomFileReply;
    class IEditingProjectComponent;
    class ProjectComponentExistingCheck;
    class PublicComponentAddedCheck;
    class PublicComponentAddedCheckResult;
}
namespace gmep
{
    class IGmepProjectSettingComponent;
    class IGmepProjectSettingComponentType;
    class IGmepCategoryInfo;
}

namespace gmepgcs
{
    /// \brief 公共构件数据传输对象
    class GCS_SERVICE_EXPORTS PublicComponentDto final
    {
    public:
        std::wstring Id;        ///< 公共构件ID
        std::wstring Name;      ///< 公共构件名称
    };

    /// \brief 公共构件是否已添加到协同项目检测数据对象
    class GCS_SERVICE_EXPORTS PublicComponentAddedCheck final
    {
    public:
        std::wstring ProjectId;                                             /// 协同项目ID
        std::vector<std::shared_ptr<PublicComponentDto>> PublicComponents;  /// 公共构件数据列表
    };

    /// \brief 公共构件是否已添加到协同项目检测结果对象
    class GCS_SERVICE_EXPORTS PublicComponentAddedCheckResult final
    {
    public:
        std::wstring PublicComponentId;   ///< 公共构件ID
        bool Exist = false;               ///< 是否已添加到协同项目
        std::wstring ProjectId;           ///< 协同项目ID
        std::wstring SpaceId;             ///< 协同空间ID
        std::wstring SuiteId;             ///< 项目构件ID（若检测到已添加）
        std::wstring Name;                ///< 项目构件名称（若检测到已添加）
        int32_t Version = -1;             ///< 项目构件修订版本号（若检测到已添加）
        std::wstring CategoryCode;        ///< 项目构件分类编码（若检测到已添加）
    };
}

namespace gmepgcs
{
    class GCS_SERVICE_EXPORTS ProjectCloudComponentService : public QObject
    {
        Q_OBJECT

    private:
        explicit ProjectCloudComponentService();
        ProjectCloudComponentService(const ProjectCloudComponentService &) = default;
        ProjectCloudComponentService &operator=(const ProjectCloudComponentService &) = default;
        virtual ~ProjectCloudComponentService();
        
    public:
        static ProjectCloudComponentService *Get();

    public:


       /* CustomReply<std::shared_ptr<IProjectComponent>> *ReplaceWithPublic(
            const std::wstring &projectId,
            const std::wstring &projectComponentId) const;*/

        CustomReply<std::shared_ptr<ProjectComponentExistingCheck>> *CheckComponentExistsById(
            const std::wstring & projectId,
            const std::wstring & componentId) const;

        // 检查公共构件是否已经在此项目被添加过
        std::unordered_map<std::wstring, bool> CheckPublicComponentAdded(const std::wstring & projectId, const std::vector<std::wstring>& publicComponentIds) const;

        /// \brief 检查公共构件是否已经在此项目被添加过
        ///
        /// \param publicComponentAddedCheck 检查所需的数据
        /// \return 检查的结果
        std::vector<std::shared_ptr<PublicComponentAddedCheckResult>> CheckPublicComponentAdded(const std::shared_ptr<PublicComponentAddedCheck> &spPublicComponentAddedCheck) const;

        // 向项目中添加公共构件
        std::map<std::wstring, ComponentInfos> AddComponentFromPublic(const std::wstring & projectId, const std::vector<std::wstring>& publicComponentIds);

      /*  CustomReply<std::shared_ptr<ISpecification>> *GetSpecification(
            const std::wstring & projectId,
            const std::wstring & componentId,
            const int32_t & componentVersion,
            const std::wstring & specificationName) const;*/
        
        /*CustomReply<std::vector<std::shared_ptr<ISpecification>>> *GetSpecifications(
            const std::wstring & projectId,
            const std::wstring & componentId,
            const int32_t & componentVersion) const;*/

       /* CustomReply<std::vector<std::shared_ptr<ILegend>>> *GetComponentLegends(
            const std::wstring &projectId, 
            const std::wstring &componentId, 
            const int32_t &componentVersion) const;*/

        CustomReply<std::wstring> *GetComponentDownloadUrl(
            const std::wstring &projectId, 
            const std::wstring &componentId, 
            const int32_t &componentVersion) const;

        CustomFileReply *DownloadComponent(
            const std::wstring & downloadUrl,
            const std::wstring &saveFilePath,
            bool isNeedToken = true ) const;


        CustomFileReply *DownloadComponentXml(
            const std::wstring &projectId,
            const std::wstring &componentId,
            const int32_t &componentVersion,
            const std::wstring &saveFilePath) const;

        bool SendModifyComponent(
            const std::wstring &projectId,
            const gmep::IGmepProjectSettingComponent* component,
            const gmep::IGmepCategoryInfo* pCategory,
            int& iVersion, // 返回新版本号， 一般+1
            const bool &force = false) const;

        bool GetComponentPlacholderIds(
            const gmep::IGmepProjectSettingComponent* component,
            std::vector<std::wstring>& publicIds, 
            std::vector<std::wstring>& enterpriseIds, 
            std::vector<std::wstring>& shareIds,
            std::vector<std::wstring>& projectLegendIds) const;

        bool GetComponentPlacholderId(
            const std::wstring& id,
            const int& placeholderFrom, 
            std::vector<std::wstring>& publicIds,
            std::vector<std::wstring>& enterpriseIds,
            std::vector<std::wstring>& shareIds,
            std::vector<std::wstring>& projectLegendIds) const;

        bool CreateComponentEnterpriseBindInfo(
            const int64_t & componentId,
            const int & componentVersion,
            const std::vector<std::wstring>& enterpriseIds,
            const std::vector<std::wstring>& shareIds,
            std::vector<std::wstring>& projectLegendIds,
            std::string & info) const;

        bool SendDeleteComponent(
            const std::wstring & projectId,
            const std::wstring & componentId,
            const int32_t & componentVersion) const;

        QJsonArray GetParamValuesOfOneType(const gmep::IGmepProjectSettingComponentType* typeItem,
            const gmep::IGmepCategoryInfo* pCategory);

        // 批量本地上传本地添加的构件到协同项目构件库
        bool ComponentBatchUploadByHttp(
            const std::wstring & projectId,
            QJsonObject& requestObject,
            std::string& strRetResponse);
        // 单个上传公共库构件到协同项目构件库（私有化环境下用本地添加方式）
        bool PublicComponentUploadForPrivateByHttp(
            const std::wstring & projectId,
            QJsonObject& requestObject,
            std::string& strRetResponse);

        // 更新或者新增图例到项目空间
        bool UpdateOrAddLegendToProjectSpace(
            const std::wstring& projectId,
            QJsonArray&  legendJsonArray,
            std::string& strRetResopnse);

        // 检查此公共图例是否在协同项目图例库已经存在
        bool PublicPlaceHolderExistInProject(const std::wstring & projectId,
            const std::vector<std::wstring>& publicPlaceHolderIdVec,
            std::map<std::wstring, GmepComponentPlaceHolderInfo>& retSharePlaceHolderInfo,
            std::map<std::wstring, GmepComponentPlaceHolderInfo>& retProjectPlaceHolderInfo,
            std::vector<std::wstring>& notExistIdVec);

        std::map<std::wstring, std::wstring> GetUnReleasedComponents(
            const std::wstring & projectId);

        //std::map<name,<type,displaytype>>
        std::map < std::wstring, std::tuple<std::wstring, std::wstring>> 
            GetParameterTypeInfo(const QJsonArray & parameterDefinitionArray) const;

        bool CheckParameterValue(
            const std::tuple<std::wstring, std::wstring>& parameterTypeInfo, 
            std::wstring & parameterValue) const;

        bool EnsureGjwLoggedIn();
    public:
      
    signals:
        void OnGotPerformanceCurveDefinitions(std::shared_ptr<std::vector<IPerformanceCurveDefinition *>> spCurveDefintions);
        void OnGotPerformanceCurve(std::shared_ptr<std::vector<IPerformanceCurve *>> spCurves);
        void OnGotLegends(std::shared_ptr<std::vector<ILegend *>> spLegends);
        void OnGotNullValue();

    private:
        void ConfigureAuthorization(QNetworkRequest &request) const;

    private:
        static ProjectCloudComponentService *s_pInstance;
        std::shared_ptr<QNetworkAccessManager> m_spNetworkManager;
        QString m_gdcModuleEndPoint;
    };
}

